package org.agony2d.view 
{
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import org.agony2d.control.Touch;
	import org.agony2d.notify.AEvent;
	import org.agony2d.notify.ATouchEvent;
	
	import org.agony2d.control.TouchManager;
	import org.agony2d.core.agony_internal;
	import org.agony2d.debug.Logger;
	import org.agony2d.view.core.AgonySprite;
	import org.agony2d.view.core.UIManager;
	import org.agony2d.notify.AEvent;
	import org.agony2d.view.puppet.NineScalePuppet;
	import org.agony2d.view.supportClasses.AbstractMultiFusion;
	import org.agony2d.utils.MathUtil;

	use namespace agony_internal;
	
	/* 
		★★★★★ 单向滚屏: ★★★★★
		mPane = new ScrollPane(400, 400)
		mPane.horizDisableOffset = Infinity
		mPane.vertiDisableOffset = 4
		this.fusion.addElement(mPane, 200, 80)
		mPane.contentHeight = 600
		mPane.addEventListener(AEvent.START_DRAG, function(e:AEvent):void
		{
			if (!AgonyUI.interactive)
			{
				TweenLite.killTweensOf(mPane)
				//trace('interactive false')
			}
		})
		mPane.addEventListener(AEvent.STOP_DRAG, function(e:AEvent):void
		{
			correctionY = mPane.vertiCorrection
			if (correctionY != 0)
			{
				AgonyUI.interactive = false
				//trace('interactive false')
				TweenLite.to(mPane, 0.6, { y:mPane.y + correctionY, 
										ease:Cubic.easeOut,
										onComplete:function():void
				{
					AgonyUI.interactive = true
					//trace('interactive true')
				}})
			}
		})
		
		★★★★★ 双向滚屏: ★★★★★
		mPane = new ScrollPane(400, 400)
		mPane.horizDisableOffset = 4
		mPane.vertiDisableOffset = 4
		this.fusion.addElement(mPane, 200, 80)
		mPane.contentWidth = 740
		mPane.contentHeight = 600
		mPane.addEventListener(AEvent.START_DRAG, function(e:AEvent):void
		{
			if (!AgonyUI.interactive)
			{
				TweenLite.killTweensOf(mPane)
				//trace('interactive false')
			}
		})
		mPane.addEventListener(AEvent.STOP_DRAG, function(e:AEvent):void
		{
			correctionX = mPane.horizCorrection
			correctionY = mPane.vertiCorrection
			if (correctionX != 0 || correctionY != 0)
			{
				AgonyUI.interactive = false
				//trace('interactive false')
				TweenLite.to(mPane, 0.6, { x:mPane.x + correctionX,
										y:mPane.y + correctionY, 
										ease:Linear.easeNone, 
										onComplete:function():void
				{
					AgonyUI.interactive = true
					//trace('interactive true')
				}})
			}
		})
		F = mPane.getHorizThumb('scroll', 400, 10)
		this.fusion.addElement(F, 200, 480)
		F = mPane.getVertiThumb('scroll', 400, 10)
		this.fusion.addElement(F, 600, 80)
	 */
		
	/**
	 * @usage
	 * 
	 * [property]
	 * 			1. ◇locked
	 * 			2. ◇limitLeft × limitRight × limitTop × limitBottom
	 * 			3. ◇contentWidth
	 * 			4. ◇contentHeight
	 * 			5. ◇horizDisableOffset
	 * 			6. ◇vertiDisableOffset
	 * 			7. ◇horizCorrection
	 * 			8. ◇vertiCorrection
	 * 			9. ◇horizRatio
	 * 			10.◇vertiRatio
	 * 
	 * [method]
	 *			1. ◆getHorizThumb
	 * 			2. ◆getVertiThumb
	 * 			3. ◆updateThumbs
	 */
public class ScrollPane extends AbstractMultiFusion
{
	
	public function ScrollPane( maskWidth:Number, maskHeight:Number, locked:Boolean = false ) 
	{
		if (maskWidth <= 0 && maskHeight <= 0) 
		{
			Logger.reportError(this, 'constructor', '视域尺寸不可为负 !!')
		}
		
		this.spaceWidth     =  m_maskWidth  = m_contentWidth  = maskWidth
		this.spaceHeight    =  m_maskHeight = m_contentHeight = maskHeight
		m_shell.scrollRect  =  new Rectangle(0, 0, maskWidth, maskHeight)
		m_locked            =  true
		this.locked         =  locked
	}
	
	
	/** ◇是否锁定 **/
	public function get locked() : Boolean { return m_locked }
	public function set locked( b:Boolean ) : void 
	{ 
		if (m_locked != b)
		{
			m_locked = b
			if (b)
			{
				TouchManager.getInstance().removeEventListener(ATouchEvent.NEW_TOUCH, __onStart)
			}
			else
			{
				TouchManager.getInstance().addEventListener(ATouchEvent.NEW_TOUCH, __onStart, false, 8000)
			}
		}
	}
	
	/** ◇拖动界限限制 **/
	public var limitLeft:Boolean
	public var limitRight:Boolean
	public var limitTop:Boolean
	public var limitBottom:Boolean
	
	/** ◇内容宽度 **/
	final public function get contentWidth() : Number { return m_contentWidth }
	final public function set contentWidth( v:Number ) : void
	{ 
		m_contentWidth = (v < m_maskWidth ? m_maskWidth : v)
		if (m_horizPuppet)
		{
			m_horizPuppet.width = m_maskWidth * m_maskWidth / m_contentWidth
		}
	}
	
	/** ◇内容高度 **/
	final public function get contentHeight() : Number { return m_contentHeight }
	final public function set contentHeight( v:Number ) : void 
	{ 
		m_contentHeight = (v < m_maskHeight ? m_maskHeight : v)
		if(m_vertiPuppet)
		{
			m_vertiPuppet.height = m_maskHeight * m_maskHeight / m_contentHeight
		}
	}
	
	/** ◇失效偏移量 **/
	final public function get horizDisableOffset() : int { return m_horizDisableOffset }
	final public function set horizDisableOffset( v:int ) : void { m_horizDisableOffset = v }
	final public function get vertiDisableOffset() : int { return m_vertiDisableOffset }
	final public function set vertiDisableOffset( v:int ) : void { m_vertiDisableOffset = v }
	
	/** ◇水平位置校正值 **/
	final public function get horizCorrection() : Number
	{
		var value:Number
		
		value = m_view.x
		if (value > 0)
		{
			return -value
		}
		else if(value < m_maskWidth - m_contentWidth)
		{
			return m_maskWidth - m_contentWidth - value
		}
		return 0
	}
	
	/** ◇垂直位置校正值 **/
	final public function get vertiCorrection() : Number 
	{
		var value:Number
		
		value = m_view.y
		if (value > 0)
		{
			return -value
		}
		else if(value < m_maskHeight - m_contentHeight)
		{
			return m_maskHeight - m_contentHeight - value
		}
		return 0
	}
	
	/** ◇水平比率(记录位置,范围0-1) **/
	public function get horizRatio() : Number { return MathUtil.getRatioBetween(m_view.x, 0, m_maskWidth  - m_contentWidth) }
	public function set horizRatio( v:Number ) : void
	{
		m_view.x = v * (m_maskWidth - m_contentWidth)
		if (m_horizThumb)
		{
			m_horizPuppet.x =  v * (m_maskWidth - m_horizPuppet.width)
		}
	}
	
	/** ◇垂直比率(记录位置,范围0-1) **/
	public function get vertiRatio() : Number { return MathUtil.getRatioBetween(m_view.y, 0, m_maskHeight - m_contentHeight)}
	public function set vertiRatio( v:Number ) : void
	{
		m_view.y = v * (m_maskHeight - m_contentHeight)
		if (m_vertiThumb)
		{
			m_vertiPuppet.y = v * (m_maskHeight - m_vertiPuppet.height)
		}
	}
	
	
	/**
	 * ◆获取水平滑块
	 * @param	dataName
	 * @param	length
	 * @param	width
	 */
	public function getHorizThumb( dataName:String, length:Number, width:Number = -1 ) : Fusion
	{
		if (!m_horizThumb)
		{
			m_horizThumb = new Fusion()
			m_horizThumb.interactive = false
			m_horizThumb.spaceWidth = length
			m_horizThumb.spaceHeight = width
			m_horizPuppet = new NineScalePuppet(dataName, length * m_maskWidth / m_contentWidth, width)
			m_horizThumb.addElement(m_horizPuppet)
		}
		return m_horizThumb
	}
	
	/**
	 * ◆获取垂直滑块
	 * @param	dataName
	 * @param	length
	 * @param	width
	 */
	public function getVertiThumb( dataName:String, length:Number, width:Number = -1 ) : Fusion
	{
		if (!m_vertiThumb)
		{
			m_vertiThumb = new Fusion()
			m_vertiThumb.interactive = false
			m_vertiThumb.spaceWidth = width
			m_vertiThumb.spaceHeight = length
			m_vertiPuppet = new NineScalePuppet(dataName, width, length * m_maskHeight / m_contentHeight)
			m_vertiThumb.addElement(m_vertiPuppet)
		}
		return m_vertiThumb
	}
	
	/**
	 * 更新滑块
	 */
	final public function updateThumbs() : void
	{
		if (m_horizThumb)
		{
			m_horizPuppet.x = MathUtil.getRatioBetween(m_view.x, 0, m_maskWidth - m_contentWidth) * (m_maskWidth - m_horizPuppet.width)
		}
		if (m_vertiThumb)
		{
			m_vertiPuppet.y = MathUtil.getRatioBetween(m_view.y, 0, m_maskHeight - m_contentHeight) * (m_maskHeight - m_vertiPuppet.height)
		}
	}
	
	
	override agony_internal function dispose() : void
	{
		if (!m_locked)
		{
			TouchManager.getInstance().removeEventListener(ATouchEvent.NEW_TOUCH, __onStart)
		}
		if (m_dragging)
		{
			this.removeEventListener(AEvent.DRAGGING, __onDragging)
			TouchManager.getInstance().primaryTouch.addEventListener(AEvent.RELEASE, __onRelease)
			if (!UIManager.m_interactive)
			{
				AgonyUI.interactive = true
			}
		}
		m_horizThumb = m_vertiThumb = null
		m_horizPuppet = m_vertiPuppet = null
		m_shell.scrollRect = null
		super.dispose()
	}
	
	
	
	agony_internal var m_horizThumb:Fusion, m_vertiThumb:Fusion
	
	agony_internal var m_horizPuppet:NineScalePuppet, m_vertiPuppet:NineScalePuppet
	
	agony_internal var m_maskWidth:Number, m_maskHeight:Number
	
	agony_internal var m_contentWidth:Number, m_contentHeight:Number
	
	agony_internal var m_startX:Number, m_startY:Number, m_oldX:Number, m_oldY:Number
	
	agony_internal var m_horizDisableOffset:int, m_vertiDisableOffset:int
	
	agony_internal var m_dragging:Boolean, m_locked:Boolean
	
	agony_internal var m_touch:Touch
	
	
	agony_internal function __onStart( e:ATouchEvent ) : void
	{
		var point:Point
		
		if (!e.touch.isPrimaryTouchPoint)
		{
			return
		}
		
		m_touch = e.touch
		point = (shell as AgonySprite).global
		m_oldX = m_startX = m_touch.stageX
		m_oldY = m_startY = m_touch.stageY
		
		if (m_startX >= point.x &&
			m_startX <= point.x + m_maskWidth * UIManager.m_pixelRatio && 
			m_startY >= point.y &&
			m_startY <= point.y + m_maskHeight * UIManager.m_pixelRatio)
		{
			this.startDrag()
			this.addEventListener(AEvent.DRAGGING, __onDragging)
			m_touch.addEventListener(AEvent.RELEASE, __onRelease, false, 8000)
			m_dragging = true
		}
	}
	
	agony_internal function __onDragging( e:AEvent ) : void
	{
		var mouseX:Number, mouseY:Number
		
		mouseX = m_touch.stageX
		mouseY = m_touch.stageY
		
		// 当发生触摸位移差达到一定程序时，屏蔽组件
		if (UIManager.m_interactive && ((Math.abs(m_oldX - m_startX) > m_horizDisableOffset || Math.abs(m_oldY - m_startY) > m_vertiDisableOffset)))
		{
			AgonyUI.interactive = false
		}
		
		this.__onLimit()
		m_oldX = mouseX
		m_oldY = mouseY
	}
	
	agony_internal function __onRelease( e:AEvent ) : void
	{
		this.removeEventListener(AEvent.DRAGGING, __onDragging)
		m_dragging = false
		
		if (!UIManager.m_interactive)
		{
			AgonyUI.interactive = true
			e.stopImmediatePropagation()
		}
		this.stopDrag(true)
	}

	final agony_internal function __onLimit() : void
	{
		if (m_view.x > 0 && limitLeft)
		{
			m_view.x = 0
		}
		else if(m_view.x < m_maskWidth - m_contentWidth && limitRight)
		{
			m_view.x = m_maskWidth - m_contentWidth
		}
		if (m_view.y > 0 && limitTop)
		{
			m_view.y = 0
		}
		else if(m_view.y < m_maskHeight - m_contentHeight && limitBottom)
		{
			m_view.y = m_maskHeight - m_contentHeight
		}
		this.updateThumbs()
	}
}
}